home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / include / sound / pcm-indirect.h < prev    next >
C/C++ Source or Header  |  2006-01-09  |  6KB  |  178 lines

  1. /*
  2.  * Helper functions for indirect PCM data transfer
  3.  *
  4.  *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
  5.  *                   Jaroslav Kysela <perex@suse.cz>
  6.  *
  7.  *   This program is free software; you can redistribute it and/or modify
  8.  *   it under the terms of the GNU General Public License as published by
  9.  *   the Free Software Foundation; either version 2 of the License, or
  10.  *   (at your option) any later version.
  11.  *
  12.  *   This program is distributed in the hope that it will be useful,
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *   GNU General Public License for more details.
  16.  *
  17.  *   You should have received a copy of the GNU General Public License
  18.  *   along with this program; if not, write to the Free Software
  19.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #ifndef __SOUND_PCM_INDIRECT_H
  23. #define __SOUND_PCM_INDIRECT_H
  24.  
  25. #include <sound/pcm.h>
  26.  
  27. typedef struct sndrv_pcm_indirect {
  28.     unsigned int hw_buffer_size;    /* Byte size of hardware buffer */
  29.     unsigned int hw_queue_size;    /* Max queue size of hw buffer (0 = buffer size) */
  30.     unsigned int hw_data;    /* Offset to next dst (or src) in hw ring buffer */
  31.     unsigned int hw_io;    /* Ring buffer hw pointer */
  32.     int hw_ready;        /* Bytes ready for play (or captured) in hw ring buffer */
  33.     unsigned int sw_buffer_size;    /* Byte size of software buffer */
  34.     unsigned int sw_data;    /* Offset to next dst (or src) in sw ring buffer */
  35.     unsigned int sw_io;    /* Current software pointer in bytes */
  36.     int sw_ready;        /* Bytes ready to be transferred to/from hw */
  37.     snd_pcm_uframes_t appl_ptr;    /* Last seen appl_ptr */
  38. } snd_pcm_indirect_t;
  39.  
  40. typedef void (*snd_pcm_indirect_copy_t)(snd_pcm_substream_t *substream,
  41.                     snd_pcm_indirect_t *rec, size_t bytes);
  42.  
  43. /*
  44.  * helper function for playback ack callback
  45.  */
  46. static inline void
  47. snd_pcm_indirect_playback_transfer(snd_pcm_substream_t *substream,
  48.                    snd_pcm_indirect_t *rec,
  49.                    snd_pcm_indirect_copy_t copy)
  50. {
  51.     snd_pcm_runtime_t *runtime = substream->runtime;
  52.     snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
  53.     snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
  54.     int qsize;
  55.  
  56.     if (diff) {
  57.         if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
  58.             diff += runtime->boundary;
  59.         rec->sw_ready += (int)frames_to_bytes(runtime, diff);
  60.         rec->appl_ptr = appl_ptr;
  61.     }
  62.     qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size;
  63.     while (rec->hw_ready < qsize && rec->sw_ready > 0) {
  64.         unsigned int hw_to_end = rec->hw_buffer_size - rec->hw_data;
  65.         unsigned int sw_to_end = rec->sw_buffer_size - rec->sw_data;
  66.         unsigned int bytes = qsize - rec->hw_ready;
  67.         if (rec->sw_ready < (int)bytes)
  68.             bytes = rec->sw_ready;
  69.         if (hw_to_end < bytes)
  70.             bytes = hw_to_end;
  71.         if (sw_to_end < bytes)
  72.             bytes = sw_to_end;
  73.         if (! bytes)
  74.             break;
  75.         copy(substream, rec, bytes);
  76.         rec->hw_data += bytes;
  77.         if (rec->hw_data == rec->hw_buffer_size)
  78.             rec->hw_data = 0;
  79.         rec->sw_data += bytes;
  80.         if (rec->sw_data == rec->sw_buffer_size)
  81.             rec->sw_data = 0;
  82.         rec->hw_ready += bytes;
  83.         rec->sw_ready -= bytes;
  84.     }
  85. }
  86.  
  87. /*
  88.  * helper function for playback pointer callback
  89.  * ptr = current byte pointer
  90.  */
  91. static inline snd_pcm_uframes_t
  92. snd_pcm_indirect_playback_pointer(snd_pcm_substream_t *substream,
  93.                   snd_pcm_indirect_t *rec, unsigned int ptr)
  94. {
  95.     int bytes = ptr - rec->hw_io;
  96.     if (bytes < 0)
  97.         bytes += rec->hw_buffer_size;
  98.     rec->hw_io = ptr;
  99.     rec->hw_ready -= bytes;
  100.     rec->sw_io += bytes;
  101.     if (rec->sw_io >= rec->sw_buffer_size)
  102.         rec->sw_io -= rec->sw_buffer_size;
  103.     if (substream->ops->ack)
  104.         substream->ops->ack(substream);
  105.     return bytes_to_frames(substream->runtime, rec->sw_io);
  106. }
  107.  
  108.  
  109. /*
  110.  * helper function for capture ack callback
  111.  */
  112. static inline void
  113. snd_pcm_indirect_capture_transfer(snd_pcm_substream_t *substream,
  114.                   snd_pcm_indirect_t *rec,
  115.                   snd_pcm_indirect_copy_t copy)
  116. {
  117.     snd_pcm_runtime_t *runtime = substream->runtime;
  118.     snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
  119.     snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
  120.  
  121.     if (diff) {
  122.         if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
  123.             diff += runtime->boundary;
  124.         rec->sw_ready -= frames_to_bytes(runtime, diff);
  125.         rec->appl_ptr = appl_ptr;
  126.     }
  127.     while (rec->hw_ready > 0 && 
  128.            rec->sw_ready < (int)rec->sw_buffer_size) {
  129.         size_t hw_to_end = rec->hw_buffer_size - rec->hw_data;
  130.         size_t sw_to_end = rec->sw_buffer_size - rec->sw_data;
  131.         size_t bytes = rec->sw_buffer_size - rec->sw_ready;
  132.         if (rec->hw_ready < (int)bytes)
  133.             bytes = rec->hw_ready;
  134.         if (hw_to_end < bytes)
  135.             bytes = hw_to_end;
  136.         if (sw_to_end < bytes)
  137.             bytes = sw_to_end;
  138.         if (! bytes)
  139.             break;
  140.         copy(substream, rec, bytes);
  141.         rec->hw_data += bytes;
  142.         if ((int)rec->hw_data == rec->hw_buffer_size)
  143.             rec->hw_data = 0;
  144.         rec->sw_data += bytes;
  145.         if (rec->sw_data == rec->sw_buffer_size)
  146.             rec->sw_data = 0;
  147.         rec->hw_ready -= bytes;
  148.         rec->sw_ready += bytes;
  149.     }
  150. }
  151.  
  152. /*
  153.  * helper function for capture pointer callback,
  154.  * ptr = current byte pointer
  155.  */
  156. static inline snd_pcm_uframes_t
  157. snd_pcm_indirect_capture_pointer(snd_pcm_substream_t *substream,
  158.                  snd_pcm_indirect_t *rec, unsigned int ptr)
  159. {
  160.     int qsize;
  161.     int bytes = ptr - rec->hw_io;
  162.     if (bytes < 0)
  163.         bytes += rec->hw_buffer_size;
  164.     rec->hw_io = ptr;
  165.     rec->hw_ready += bytes;
  166.     qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size;
  167.     if (rec->hw_ready > qsize)
  168.         return SNDRV_PCM_POS_XRUN;
  169.     rec->sw_io += bytes;
  170.     if (rec->sw_io >= rec->sw_buffer_size)
  171.         rec->sw_io -= rec->sw_buffer_size;
  172.     if (substream->ops->ack)
  173.         substream->ops->ack(substream);
  174.     return bytes_to_frames(substream->runtime, rec->sw_io);
  175. }
  176.  
  177. #endif /* __SOUND_PCM_INDIRECT_H */
  178.